# -*- coding: utf-8 -*-
import random

from PIL import Image


def huidu_JZ(org_image, threshold=100):
    """
    灰度降噪
    :param org_image: 原始图片
    :param threshold: 阙值
    :return:
    """
    image = org_image.convert('L')  # 转换为灰度图像，即RGB通道从3变为1
    image2 = Image.new("L", image.size, 255)
    for y in range(image.height):
        for x in range(image.width):
            pix = image.getpixel((x, y))
            if int(pix) > threshold:  # 调整灰度
                image2.putpixel((x, y), 1)
            else:
                image2.putpixel((x, y), 0)
    return image2


def huidu_JZ_keep_color(org_image, threshold=100):
    """
    灰度降噪，保留RGB颜色
    :param org_image: 原始图片
    :param threshold: 阙值
    :return:
    """
    cache = []
    # 记录有内容的点
    image = huidu_JZ(org_image, threshold)
    for x in range(image.width):
        for y in range(image.height):
            if image.getpixel((x, y)) == 0:
                cache.append((x, y))
    # 删除原图片中无内容的点
    for x in range(org_image.width):
        for y in range(org_image.height):
            if not (x, y) in cache:
                org_image.putpixel((x, y), (255, 255, 255))
    return org_image


# def get_bin_table(threshold=140):
#     """
#     获取灰度转二值的映射table
#     :param threshold:
#     :return:
#     """
#     table = []
#     for i in range(256):
#         if i < threshold:
#             table.append(0)
#         else:
#             table.append(1)
#
#     return table


def _9_gg_JZ(image, threshold=3):
    """
    9宫格降噪
    :param image:
    :return:
    """
    # 9宫格降噪
    width = image.width
    height = image.height
    for y in range(height):
        for x in range(width):
            sum = sum_9_region(image, x, y)
            if sum <= threshold:
                image.putpixel((x, y), 1)
    return image


def sum_9_region(image, x, y):
    """
    9邻域框,以当前点为中心的田字框,计算周围点的个数
    :param image:
    :param x:
    :param y:
    :return:
    """
    # todo 判断图片的长宽度下限
    cur_pixel = image.getpixel((x, y))  # 当前像素点的值
    width = image.width
    height = image.height

    if cur_pixel == 1:  # 如果当前点为白色区域,则不统计邻域值
        return 0

    if y == 0:  # 第一行
        if x == 0:  # 左上顶点,4邻域
            # 中心点旁边3个点
            sum = cur_pixel \
                  + image.getpixel((x, y + 1)) \
                  + image.getpixel((x + 1, y)) \
                  + image.getpixel((x + 1, y + 1))
            return 4 - sum
        elif x == width - 1:  # 右上顶点
            sum = cur_pixel \
                  + image.getpixel((x, y + 1)) \
                  + image.getpixel((x - 1, y)) \
                  + image.getpixel((x - 1, y + 1))

            return 4 - sum
        else:  # 最上非顶点,6邻域
            sum = image.getpixel((x - 1, y)) \
                  + image.getpixel((x - 1, y + 1)) \
                  + cur_pixel \
                  + image.getpixel((x, y + 1)) \
                  + image.getpixel((x + 1, y)) \
                  + image.getpixel((x + 1, y + 1))
            return 6 - sum
    elif y == height - 1:  # 最下面一行
        if x == 0:  # 左下顶点
            # 中心点旁边3个点
            sum = cur_pixel \
                  + image.getpixel((x + 1, y)) \
                  + image.getpixel((x + 1, y - 1)) \
                  + image.getpixel((x, y - 1))
            return 4 - sum
        elif x == width - 1:  # 右下顶点
            sum = cur_pixel \
                  + image.getpixel((x, y - 1)) \
                  + image.getpixel((x - 1, y)) \
                  + image.getpixel((x - 1, y - 1))

            return 4 - sum
        else:  # 最下非顶点,6邻域
            sum = cur_pixel \
                  + image.getpixel((x - 1, y)) \
                  + image.getpixel((x + 1, y)) \
                  + image.getpixel((x, y - 1)) \
                  + image.getpixel((x - 1, y - 1)) \
                  + image.getpixel((x + 1, y - 1))
            return 6 - sum
    else:  # y不在边界
        if x == 0:  # 左边非顶点
            sum = image.getpixel((x, y - 1)) \
                  + cur_pixel \
                  + image.getpixel((x, y + 1)) \
                  + image.getpixel((x + 1, y - 1)) \
                  + image.getpixel((x + 1, y)) \
                  + image.getpixel((x + 1, y + 1))

            return 6 - sum
        elif x == width - 1:  # 右边非顶点
            # print('%s,%s' % (x, y))
            sum = image.getpixel((x, y - 1)) \
                  + cur_pixel \
                  + image.getpixel((x, y + 1)) \
                  + image.getpixel((x - 1, y - 1)) \
                  + image.getpixel((x - 1, y)) \
                  + image.getpixel((x - 1, y + 1))

            return 6 - sum
        else:  # 具备9领域条件的
            sum = image.getpixel((x - 1, y - 1)) \
                  + image.getpixel((x - 1, y)) \
                  + image.getpixel((x - 1, y + 1)) \
                  + image.getpixel((x, y - 1)) \
                  + cur_pixel \
                  + image.getpixel((x, y + 1)) \
                  + image.getpixel((x + 1, y - 1)) \
                  + image.getpixel((x + 1, y)) \
                  + image.getpixel((x + 1, y + 1))
            return 9 - sum


def get_crop_imgs(img):
    """
    按照图片的特点,进行切割,这个要根据具体的验证码来进行工作. # 见原理图
    :param img:
    :return:
    """
    child_img_list = []
    for i in range(4):
        x = 2 + i * (6 + 4)  # 见原理图
        y = 0
        child_img = img.crop((x, y, x + 6, y + 10))
        child_img_list.append(child_img)

    return child_img_list


def print_image(image):
    """
    print image
    :return:
    """
    width = image.width
    height = image.height
    for y in range(height):
        for x in range(width):
            print(image.getpixel((x, y)), end="")
        print("")


def remove_border(image, point_num=3):
    """
    去边框
    :param image:
    :param point_num: 需要判断的坐标点数目。数目与准确度成正比，与效率成反比
    :return:
    """
    # 存放需要删除的 x、y 点
    flag_cache_x = []
    flag_cache_y = []

    height = image.height
    width = image.width
    # 存放需要计算的 x、y 点
    x_points = []
    y_points = []
    for i in range(point_num):
        x_points.append(random.randint(0, width - 1))
        y_points.append(random.randint(0, height - 1))

    # 计算横线
    for fix_x in x_points:
        for y in range(height):
            # 已确定的y位置不需要计算
            if y in flag_cache_y:
                continue
            # 中间的点不需要计算
            if 0.3 < y / height < 0.7:
                continue
            # 空白点不需要计算
            if image.getpixel((fix_x, y)) == 1:
                continue
            point_count = 0
            for x in range(width):
                if image.getpixel((x, y)) == 0:
                    point_count += 1
            if point_count / width > 0.8:
                flag_cache_y.append(y)
    # 计算竖线
    for fix_y in y_points:
        for x in range(width):
            # 已确定的x位置不需要计算
            if x in flag_cache_x:
                continue
            # 中间的点不需要计算
            if 0.3 < x / width < 0.7:
                continue
            # 空白点不需要计算
            if image.getpixel((x, fix_y)) == 1:
                continue
            point_count = 0
            for y in range(height):
                if image.getpixel((x, y)) == 0:
                    point_count += 1
            if point_count / height > 0.8:
                flag_cache_x.append(x)

    for y in flag_cache_y:
        for x in range(width):
            image.putpixel((x, y), 1)
    for x in flag_cache_x:
        for y in range(height):
            image.putpixel((x, y), 1)
    return image


def image_crop(image, char_sum):
    """
    提取图片中的字符
    :param image: 待提取图片
    :param char_sum: 图片字符总数
    :return:
    """
    records = []  # 结果集

    height = image.height
    width = image.width

    central_y = int(height / 2)

    for x in range(width):
        point = image.getpixel((x, central_y))
        if point != 0:
            continue
        # 找到顶点、最左、右、底侧的点
        top, bottom, left, right = find_margin(image, x, central_y)

        records.append(cut_image(image, top, bottom, left, right))

    if len(records) == char_sum:
        return records

    # 去除非字符的干扰区域
    max_pixel = 0
    for item in records:
        sum_pixel = item.height * item.width
        if sum_pixel > max_pixel:
            max_pixel = sum_pixel
    for item in records:
        if item.height * item.width / max_pixel < 0.8:
            records.remove(item)
    return records


def cut_image(image, top, bottom, left, right):
    """
    分离出图片
    :param image:
    :param top:
    :param bottom:
    :param left:
    :param right:
    :return:
    """
    child_image = image.crop((left, top, right + 1, bottom + 1))
    for x in range(child_image.width):
        for y in range(child_image.height):
            pixel = child_image.getpixel((x, y))
            if pixel == 2:
                child_image.putpixel((x, y), 0)
    return child_image


def find_margin(image, x, y):
    """
    查找最高点、最低点
    :param image: 图片
    :param x:
    :param y:
    :return: top / bottom / left / right
    """
    records_x, records_y = __find_point(image, x, y)
    records_x.sort()
    records_y.sort()
    return records_y[0], records_y[len(records_y) - 1], records_x[0], records_x[len(records_x) - 1]


def __find_point(image, x, y):
    # 添加自身，并将自身设置为空
    records_x = [x]
    records_y = [y]
    image.putpixel((x, y), 2)
    # 周围像素点处理
    # left top
    if x != 0 and y != 0:
        left_top = image.getpixel((x - 1, y - 1))
        if left_top == 0:
            result_x, result_y = __find_point(image, x - 1, y - 1)
            records_x.extend(result_x)
            records_y.extend(result_y)
    # top
    if y != 0:
        top = image.getpixel((x, y - 1))
        if top == 0:
            result_x, result_y = __find_point(image, x, y - 1)
            records_x.extend(result_x)
            records_y.extend(result_y)
    # right top
    if y != 0 and x < image.width - 1:
        right_top = image.getpixel((x + 1, y - 1))
        if right_top == 0:
            result_x, result_y = __find_point(image, x + 1, y - 1)
            records_x.extend(result_x)
            records_y.extend(result_y)
    # left
    if x != 0:
        left = image.getpixel((x - 1, y))
        if left == 0:
            result_x, result_y = __find_point(image, x - 1, y)
            records_x.extend(result_x)
            records_y.extend(result_y)
    # right
    if x < image.width - 1:
        right = image.getpixel((x + 1, y))
        if right == 0:
            result_x, result_y = __find_point(image, x + 1, y)
            records_x.extend(result_x)
            records_y.extend(result_y)
    # left bottom
    if x != 0 and y < image.height - 1:
        left_bottom = image.getpixel((x - 1, y + 1))
        if left_bottom == 0:
            result_x, result_y = __find_point(image, x - 1, y + 1)
            records_x.extend(result_x)
            records_y.extend(result_y)
    # bottom
    if y < image.height - 1:
        bottom = image.getpixel((x, y + 1))
        if bottom == 0:
            result_x, result_y = __find_point(image, x, y + 1)
            records_x.extend(result_x)
            records_y.extend(result_y)
    # right bottom
    if x < image.width - 1 and y < image.height - 1:
        right_bottom = image.getpixel((x + 1, y + 1))
        if right_bottom == 0:
            result_x, result_y = __find_point(image, x + 1, y + 1)
            records_x.extend(result_x)
            records_y.extend(result_y)
    return records_x, records_y


if __name__ == '__main__':
    for i in range(5):
        print(i)
    print()
